package com.yazdankhah.utils;

import com.yazdankhah.application.Const;
import com.yazdankhah.beans.Combo;
import com.yazdankhah.beans.MyQuran;
import com.yazdankhah.beans.VerseAddr;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;

/**
 * This class represents all type of country codes and is being used for the key of a map set.
 */
public class DataTools {

  /**
   * Holds the verse address and the serial.
   */
  private static final Map<VerseAddr, Integer> addressMap = new HashMap<>(Const.VERSE_NUM);

  private static final List<VerseAddr> reverseAddressMap = new ArrayList<>(Const.VERSE_NUM);

  private static MyQuran myQuran;
  
  
  private static Logger logger = Logger.getLogger(DataTools.class);
  


  /**
   * Used singleton pattern.
   */
  private DataTools() {
    super();
  } //constructor
  
  
  public static Combo lookupQuran(int chapter, int verse) {
    
    Integer serial = getSerial(chapter, verse);
    
    if (serial < 0) return null;
        
    return lookupQuran(serial);

  } //method


  public static Combo lookupQuran(int serial) {
    
    if (serial < 0 || serial >= Const.VERSE_NUM) return null;
    
    String quranVerse = myQuran.getQuran().get(serial);
    List<String> translations = lookupTranslations(serial);
    
    String combination = combine(translations);
    
    return new Combo(quranVerse, translations, combination);

  } //method
  
  
  private static String combine(List<String> translations) {
    
    StringBuilder sb = new StringBuilder("\n\n");
    
    for (String trans : translations) {
      sb.append(trans).append("\n\n");
      
//      System.out.println("trans = [" + trans + "]");
      
    }
    return sb.toString();
  }
  

  private static List<String> lookupTranslations(int serial) {
    
    if (serial < 0 || serial >= Const.VERSE_NUM) return null;
    
    List<String> translations = new ArrayList<>();
    
    for (List<String> trans : myQuran.getTranslations()) {
      translations.add(trans.get(serial));
    }
    
    return translations;

  } //method
  

  public static int getSerial(int chapter, int verse) {
    
    Integer serial = addressMap.get(new VerseAddr(chapter, verse));
    
    if (serial == null) return 0;
    
    return serial;
    
  } //method


  public static VerseAddr getVerseAddr(int serial) {
    
    if (serial < 0 || serial >= Const.VERSE_NUM) return null;
    
    return reverseAddressMap.get(serial);

  } //method


  public static void loadMyQuran(String rootPath) {
    
    myQuran = new MyQuran();
    
    String quranFile = rootPath + Const.QURAN_HOME + Const.QURAN_FILE_NAME;
    String transFolder = rootPath + Const.TRANSLATIONS_HOME;
    
    //Note: the root path address can be different on different application servers. 
    //For example, in weblogic it brings the root path including the final "/".
    List<String> tempQuran = loadQuran(quranFile);
    myQuran.setQuran(tempQuran);
    
    List<List<String>> tempTranslations = loadTranslations(transFolder);
    myQuran.setTranslations(tempTranslations);
    
  } //method


  /**
   * Reads the given file and loads Quran's file and return it as an array list.
   *
   * @param inFN - the given quran's file name
   * @return Quran's verses
   */
  private static List<String> loadQuran(String inFN) {
    
    List<String> tempQuran = new ArrayList<>();
    
    BufferedReader reader;

    try {
      reader = new BufferedReader(new InputStreamReader(
              new FileInputStream(inFN), Charset.forName("UTF-8")));

      //int index = 1;

      //while (reader.ready()) {
      //We are sure that the number of verses is 6236.
      for (int index = 0; index < Const.VERSE_NUM; index++) {

        String line = reader.readLine().trim();
        
        //if (line.isEmpty()) continue;
        
        String[] tempLst = line.split(Const.DELEMETER);
//        System.out.println("tempLst[2] = {" + tempLst[2] + "}");

        int chapter = Integer.parseInt(tempLst[0]);
        int verse = Integer.parseInt(tempLst[1]);
        VerseAddr versAddr = new VerseAddr(chapter, verse);
        
        addressMap.put(versAddr, index);
        reverseAddressMap.add(versAddr);
        tempQuran.add(tempLst[2]);

      } //while

      reader.close();
      
      return tempQuran;

    } catch (FileNotFoundException ex) {
      System.err.println(ex.getMessage());
      return null;
    } catch (IOException ex) {
      System.err.println(ex.getMessage());
      return null;
    }

  } //method


  private static void testloadQuran() {

    //String inFN  = ".\\translation\\fa.fooladvand.txt";
    String file = ".\\quran\\quran.txt";
    List<String> tempQuran = loadQuran(file);

    GenUtil.showArrayList(tempQuran);

//    System.out.println("(1,7) = [" + lookupQuranVerse(1, 7) + "]");
//    System.out.println("(2,1) = [" + lookupQuranVerse(2, 1) + "]");
//    System.out.println("(1,3) = [" + lookupQuranVerse(1, 3) + "]");

  } //test method


  /**
   * Reads the given translation file and construct an array list of the translation and return it.
   *
   * @param inFN - the given input file name
   * @return the array list containing the verses translations.
   */
  private static List<String> loadOneTranslation(String inFN) {
    
    List<String> transVersesList = new ArrayList<>(Const.VERSE_NUM);
    
    BufferedReader reader;

    try {
      reader = new BufferedReader(new InputStreamReader(
              new FileInputStream(inFN), Charset.forName("UTF-8")));

      //We are sure that the number of verses is 6236.
      for (int index = 0; index < Const.VERSE_NUM; index++) {

        String line = reader.readLine().trim();
        String[] tempLst = line.split(Const.DELEMETER);
        transVersesList.add(tempLst[2]);

      } //while

      reader.close();

    } catch (FileNotFoundException ex) {
      System.err.println(ex.getMessage());
    } catch (IOException ex) {
      System.err.println(ex.getMessage());
    }
    
    return transVersesList;

  } //method


  private static void testloadOneTranslation() {

    //String inFN  = ".\\translation\\fa.fooladvand.txt";
    String file = ".\\translation\\fa.ayati.txt";
    List<String> trans1 = loadOneTranslation(file);

    GenUtil.showArrayList(trans1);
//
//    System.out.println("(1,7) = [" + lookupTransVerse(1, 7) + "]");
//    System.out.println("(2,1) = [" + lookupTransVerse(2, 1) + "]");
//    System.out.println("(1,3) = [" + lookupTransVerse(1, 3) + "]");

  } //test method


  /**
   * Reads the given translation file and construct an array list.
   *
   * @param inFN - the given input file name
   */
  private static List<List<String>> loadTranslations(String folderFullPath) {
    
    List<List<String>> tempTranslations  = new ArrayList<>();
    List<String> transNames = FileUtil.getFolderFNPlusPathArr(folderFullPath);
    Collections.sort(transNames);
    //GenUtil.showArrayList(transNames);
    
    for (String transFile : transNames) {
      List<String> tempTrans = loadOneTranslation(transFile);
      tempTranslations.add(tempTrans);
    }
    
    return tempTranslations;
    
  } //method


  private static void testloadTranslations() {

    //String inFN  = ".\\translation\\fa.fooladvand.txt";
    String folder = "translation";
    List<List<String>> tempTranslations = loadTranslations(folder);
    GenUtil.showArrayList(tempTranslations);
    

  } //test method


  /**
   */
// ........................ M A I N   M E T H O D ............................//
  /**
   * This main method is just for testing this class.
   *
   * @param args - the arguments
   */
  public static void main(String[] args) {

    /* ....................................................*/
    testloadTranslations();
    /* ....................................................*/

  } //main method

} //class
